/*
 * MainApplication.cpp
 *
 *  Created on: Mar 29, 2017
 *      Author: zhangjf
 */

#include <Poco/Logger.h>
#include <Poco/AutoPtr.h>
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Parser.h>
#include <Poco/Util/Application.h>
#include <Poco/FileChannel.h>
#include <Poco/DateTimeFormatter.h>
#include <Poco/PatternFormatter.h>
#include <Poco/FormattingChannel.h>

using namespace std;
using namespace Poco;
using namespace Poco::Util;
using namespace Poco::JSON;

#include "Helper.h"
#include "SessionManager.h"
#include "MainApplication.h"

Logger *pLogger = nullptr;

MainApplication::MainApplication()
{
	// TODO Auto-generated constructor stub

}

MainApplication::~MainApplication()
{
	// TODO Auto-generated destructor stub
}

int MainApplication::main(const std::vector<std::string>& args)
{
	initLogger(std::string(this->commandName() + ".log"));
	SessionManager::initialize(SessionManager::SOCKET_MODE_SERVER);

	char buffer[1024];
	while (true)
	{
		SocketAddress client;
		int n = SessionManager::receiveFrom(buffer, sizeof(buffer) - 1, client);
		buffer[n] = 0;

		const std::string msg(buffer, n);
		std::string strResp;
		doRequest(msg, strResp);

		SessionManager::sendTo(strResp.data(), strResp.length(), client);
	}

	return 0;
}

void MainApplication::doRequest(const std::string& strRequest, std::string& strResp)
{
	try
	{
		Parser parser;
		Var varMsg = parser.parse(strRequest);

		Object::Ptr joMsg = varMsg.extract<Object::Ptr>();
		if (joMsg->has("method") && joMsg->has("params"))
		{
			std::string cmd = joMsg->getValue<std::string>("method");
			Var params = joMsg->get("params");
			if (cmd == "Login")
			{
				SessionManager::doLogin(params, strResp);
			}
			else if (cmd == "Query")
			{
				SessionManager::doQuery(params, strResp);
			}
			else if (cmd == "Logout")
			{
				SessionManager::doLogout(params, strResp);
			}
			else
			{
				//poco_information(*pLogger, std::string(__func__) + "," +  std::to_string(__LINE__) + ": " + "AAAAAAAAAAAAAAAAAAAA");
			}
		}
		else
		{
			Object joResp;
			joResp.set("result", "failed");
			joResp.set("reason", "invalid session command and parameters");
			//poco_information(*pLogger, std::string(__func__) + "," +  std::to_string(__LINE__) + ": " + "AAAAAAAAAAAAAAAAAAAA");

			strResp = ((DynamicStruct)joResp).toString();
		}
	}
	catch(Exception &exc)
	{
		Object joResp;
		joResp.set("result", "failed");
		joResp.set("reason", exc.what());
		//poco_information(*pLogger, std::string(__func__) + "," +  std::to_string(__LINE__) + ": " + "AAAAAAAAAAAAAAAAAAAA");

		strResp = ((DynamicStruct)joResp).toString();
	}
}

void MainApplication::initLogger(const std::string& strLogName)
{
	AutoPtr<FileChannel> pChannel(new FileChannel);
	pChannel->setProperty("path", strLogName);
	pChannel->setProperty("rotation", "2 M");
	pChannel->setProperty("archive", "timestamp");

	AutoPtr<PatternFormatter> pPF(new PatternFormatter);
	pPF->setProperty("pattern", "%Y-%m-%d %H:%M:%S %s: %t");
	pPF->setProperty("times","local");
	AutoPtr<FormattingChannel> pFC(new FormattingChannel(pPF, pChannel));
	logger().setChannel(pFC);

	pLogger = &logger();
}

int main(int argc, char** argv)
{
	Poco::AutoPtr<MainApplication> pApp = new MainApplication;
	try
	{
		pApp->init(argc, argv);
		return pApp->run();
	}
	catch (Poco::Exception& exc)
	{
		poco_error(*pLogger, exc.displayText());
		return Poco::Util::Application::EXIT_CONFIG;
	}

	return Application::EXIT_OK;
}
